package yartiss.engine.simulation.scheduling.policies.tools;

import yartiss.engine.simulation.IEnergyProfile;
import yartiss.engine.simulation.system.ITask;
import yartiss.engine.simulation.system.ITaskSet;

public class DPSlackEnergyManager {

	public long getSlackEnergy(long t, ITaskSet taskset, IEnergyProfile energyProfile){
		long slack = Long.MAX_VALUE;;
		long time = -12;
		long dj = taskset.getActiveTasks(t).first().getNextAbsoluteDeadline(t);
		if(t==time)System.out.println(t+"--"+dj+" toto ="+taskset.getActiveTasks(t).first().getDeadline());
		for (ITask task : taskset) {
			long nextActivation  = t,nextDeadline;
			if(t==time)System.out.println("--------- "+task.getDeadline());
			do{
				nextActivation = task.getNextActivation(nextActivation);
				nextDeadline = task.getNextAbsoluteDeadline(nextActivation);
				if(nextActivation > t && nextDeadline <= dj){
					long Aj = Aj(taskset, t, nextDeadline);
					if(t==time)System.out.println("activation="+nextActivation+"   E(t)="+energyProfile.getCurrentEnergyLevel()+"  /Pr="+energyProfile.howMuchCanRecharge(nextDeadline - t)+"  Aj="+Aj);
					slack = Math.min(slack, energyProfile.getCurrentEnergyLevel() + energyProfile.howMuchCanRecharge(nextDeadline - t) - Aj);
				}
			}while( nextActivation < dj);
		}
		return slack;
	}

	private long Aj(ITaskSet taskSet, long t1, long t2) {
		long duration = t2 - t1;
		long energyDemand = 0;
		for (ITask task : taskSet) {
			long nextActivation  = t1,nextDeadline;
			do{
				nextActivation = task.getNextActivation(nextActivation);
				nextDeadline =task.getNextAbsoluteDeadline(nextActivation);
				if(nextActivation > t1 && nextDeadline <= t2 && task.getDeadline()<= duration){
					energyDemand += ( (duration - task.getDeadline()) / task.getPeriod() + 1 ) * task.getWcee();
				}
			}while( nextActivation < t2);
		}
		return energyDemand;
	}
}
